package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜品业务实现
 *
 * @Author itcast
 * @Create 2023/3/7
 **/
@Service
@Slf4j
public class DishServiceImpl implements DishService {

	@Autowired
	private DishMapper dishMapper;
	@Autowired
	private DishFlavorMapper dishFlavorMapper;

	/**
	 * 新增菜品
	 *
	 * @param dishDTO
	 */
	@Transactional
	public void saveWithFlavor(DishDTO dishDTO) {
		Dish dish = new Dish();
		BeanUtils.copyProperties(dishDTO, dish);

        /*dish.setCreateTime(LocalDateTime.now());
        dish.setUpdateTime(LocalDateTime.now());
        dish.setCreateUser(BaseContext.getCurrentId());
        dish.setUpdateUser(BaseContext.getCurrentId());*/

		// 向菜品表插入1条数据
		dishMapper.insert(dish);

		// 获取主键值
		Long dishId = dish.getId();

		List<DishFlavor> dishFlavors = dishDTO.getFlavors();
		if (dishFlavors != null && dishFlavors.size() > 0) {
			dishFlavors.forEach(dishFlavor -> {
				// 为菜品id赋值
				dishFlavor.setDishId(dishId);
			});
			// 向口味表插入n条数据
			dishFlavorMapper.insertBatch(dishFlavors);
		}

		//清理缓存
		redisTemplate.delete(DISH_FLAAVOR_KEY + dishDTO.getCategoryId());
	}

	/**
	 * 菜品分页查询
	 *
	 * @param dishPageQueryDTO
	 * @return
	 */
	public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
		PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
		Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
		return new PageResult(page.getTotal(), page.getResult());
	}

	/**
	 * 批量删除菜品
	 *
	 * @param ids
	 */
	@Transactional
	public void deleteBatch(List<Long> ids) {
		// 查询一下菜品表，看看售卖状态  ---dish
		for (Long id : ids) {
			Dish dish = dishMapper.getById(id);
			if (dish.getStatus() == StatusConstant.ENABLE) {
				// 当前菜品在售状态，不能删除
				throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
			}
		}

		//清理缓存
		if (!CollectionUtils.isEmpty(ids)){
			ids.stream().forEach(x->{
				Dish dish = dishMapper.getById(x);
				redisTemplate.delete(DISH_FLAAVOR_KEY + dish.getCategoryId());
			});
		}

		// TODO 查询一下套餐菜品关系表，查看菜品是否被关联了，如果菜品被套餐关联，则不能删除

		for (Long id : ids) {
			// 从菜品表删除一条数据---dish
			dishMapper.deleteById(id);

			// 从口味表删除当前菜品关联的口味数据----dish_flavor
			dishFlavorMapper.deleteByDishId(id);
		}
	}

	/**
	 * 根据id查询菜品和口味
	 *
	 * @param id
	 * @return
	 */
	public DishVO getByIdWithFlavor(Long id) {
		// 根据id查询菜品表，获取菜品的基本信息
		Dish dish = dishMapper.getById(id);

		// 根据菜品id查询口味表，获取口味数据
		List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);

		// 将查询到的两部分数据封装到VO中
		DishVO dishVO = new DishVO();
		BeanUtils.copyProperties(dish, dishVO);
		dishVO.setFlavors(dishFlavors);

		return dishVO;
	}

	/**
	 * 根据id修改菜品
	 *
	 * @param dishDTO
	 */
	@Transactional
	public void updateWithFlavor(DishDTO dishDTO) {
		// 1、删除原来的菜品关联的所有口味
		dishFlavorMapper.deleteByDishId(dishDTO.getId());

		// 2、再重新添加一遍口味
		List<DishFlavor> flavors = dishDTO.getFlavors();
		for (DishFlavor flavor : flavors) {
			flavor.setDishId(dishDTO.getId());
		}

		if (flavors != null && flavors.size() > 0) {
			dishFlavorMapper.insertBatch(flavors);
		}

		// 3、更新菜品表，根据id修改数据
		Dish dish = new Dish();
		BeanUtils.copyProperties(dishDTO, dish);
        /*dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());*/
		dishMapper.update(dish);

		//清理缓存
		redisTemplate.delete(DISH_FLAAVOR_KEY + dishDTO.getCategoryId());
	}

	/**
	 * 菜品起售停售
	 *
	 * @param status
	 * @param id
	 */
	public void startOrStop(Integer status, Long id) {
		Dish dish = Dish.builder()
				.id(id)
				.status(status)
				.updateTime(LocalDateTime.now())
				.updateUser(BaseContext.getCurrentId())
				.build();
		dishMapper.update(dish);

		//清理缓存
		Dish dishDB = dishMapper.getById(id);
		redisTemplate.delete(DISH_FLAAVOR_KEY + dishDB.getCategoryId());
	}

	/**
	 * 根据分类查询菜品
	 *
	 * @param categoryId
	 * @return
	 */
	@Override
	public List<Dish> list(Long categoryId) {
		Dish dish = Dish.builder()
				.categoryId(categoryId)
				.status(StatusConstant.ENABLE).build();
		return dishMapper.lish(dish);
	}


	private static final String DISH_FLAAVOR_KEY = "dish:";

	@Autowired
	private StringRedisTemplate redisTemplate;

	/**
	 * 条件查询菜品和口味
	 *
	 * @param dish
	 * @return
	 */
	public List<DishVO> listWithFlavor(Dish dish) {
		// 从Redis中查询
		String dishListJSON = redisTemplate.opsForValue().get(DISH_FLAAVOR_KEY + dish.getCategoryId());
		List<DishVO> dishVOList = JSON.parseArray(dishListJSON, DishVO.class);
		if (!CollectionUtils.isEmpty(dishVOList)){
			return dishVOList;
		}

		//缓存中没有则从数据库中查找
		List<Dish> dishList = dishMapper.lish(dish);

		if (!CollectionUtils.isEmpty(dishList)){
			dishVOList = dishList.stream().map(x -> {
				DishVO dishVO = new DishVO();
				BeanUtils.copyProperties(x, dishVO);

				// 根据菜品id查询对应的口味
				List<DishFlavor> flavors = dishFlavorMapper.getByDishId(x.getId());
				if (!CollectionUtils.isEmpty(flavors)) {
					dishVO.setFlavors(flavors);
				}
				// dishVOList.add(dishVO);
				return dishVO;
			}).collect(Collectors.toList());

			//3. 将表中查到的菜品列表添加到缓存中
			redisTemplate.opsForValue().set(DISH_FLAAVOR_KEY + dish.getCategoryId(),JSON.toJSONString(dishVOList));
		}
		return dishVOList;
	}

}
